Analysis of feedforward loops¶


Learning outcomes

  • You can define the classification basis for feedforward loops.
  • You can list the two most common feedforward loops types in microorganisms.
  • You can infer coherent/incoherent signal conversion in simple networks.
  • You can distinguish and, or and or for single promoter occupancy in mathematical models.
  • You can develop
  • The I1-FFL with AND logic is a pulse generator and also speeds response compared to an unregulated circuit.

Concept

  • When multiple factors regulate a single gene, we need to specify the logic of the regulation, usually OR or AND.

In [1]:
import numpy as np
import os
import sys
import scipy.integrate

# try importing biocircuits, if not then install it
try:
    import biocircuits
except ImportError:
    print("biocircuits not found, installing...")
    !pip install biocircuits
    import biocircuits
import biocircuits.apps

import colorcet
colors = colorcet.b_glasbey_category10

try:
    import bokeh.io
except ImportError:
    print("bokeh not found, installing...")
    !pip install bokeh
    import bokeh.io
import bokeh.layouts
import bokeh.models
import bokeh.plotting

bokeh.io.output_notebook()

Target_Dir = os.path.join(os.getcwd(),'Data','BioMotifSim')

print('Done!')
Loading BokehJS ...
Done!
In [2]:
# Function for plotting the phase plane with bokeh
def xyz_im_plot(x, y, z, x_log, y_log, z_log, title=None, palette="Viridis256"):
    """Display x, y, z data as an image."""
    p_log = bokeh.plotting.figure(
        frame_height=200,
        frame_width=200,
        x_range=(x_log.min(), x_log.max()),
        y_range=(y_log.min(), y_log.max()),
        x_axis_label="x",
        y_axis_label="y",
        title=title,
        toolbar_location=None,
        x_axis_type="log",
        y_axis_type="log",
    )
    p_log.image(
        image=[z_log],
        x=x_log.min(),
        y=y_log.min(),
        dw=x_log.max() - x_log.min(),
        dh=x_log.max() - x_log.min(),
        palette=palette,
        alpha=0.8,
    )

    p = bokeh.plotting.figure(
        frame_height=200,
        frame_width=200,
        x_range=(x.min(), x.max()),
        y_range=(y.min(), y.max()),
        x_axis_label="x",
        y_axis_label="y",
        title=title,
        toolbar_location=None,
    )
    p.image(
        image=[z],
        x=x.min(),
        y=y.min(),
        dw=x.max() - x.min(),
        dh=x.max() - x.min(),
        palette=palette,
        alpha=0.8,
    )

    p_log.visible = True
    p.visible = False

    radio_button_group = bokeh.models.RadioButtonGroup(
        labels=["log", "linear"], active=0, width=100
    )
    col = bokeh.layouts.column(
        p_log, p, bokeh.layouts.row(bokeh.models.Spacer(width=100), radio_button_group)
    )
    radio_button_group.js_on_change(
        "active",
        bokeh.models.CustomJS(
            args=dict(p_log=p_log, p=p),
            code="""
      if (p_log.visible == true) {
        p_log.visible = false;
        p.visible = true;
      }
      else {
        p_log.visible = true;
        p.visible = false;
      }
    """,
        )
    )

    return col

There are many kinds of FFLs¶

We can classify the overall FFL motif into $2^3=8$ different categories depending on which of its 3 arrows are positive or negative:

Feedforward loop classes

In this classification, half of the FFL architectures are coherent, meaning that X's direct regulation of Z and its indirect regulation of Z are of the same type, both activating or both repressing. the other half are incoherent, meaning that the direct and indirect regulatory paths have the opposite sign.

We can further sub-classify the FFLS, according to how the regulatory arrows converging on the third node (now labeled "Z") combine. Consider first the example where both X and Y activate Z, as in the C1-FFL and I4-FFl. In AND regulation, both X and Y need to be simultaneously present at high levels for Z to be expressed. In OR regulation, either input being at a high level is sufficient to activate Z.

The material presented here are excerpts from a Jupyter-book by Elowitz and Bois, there you find more detailed treatment and further examples. We will develop foundational concepts, approaches, and examples that will enable us to address these critical biological challenges. The key premise is that many of these problems can be addressed by thinking of biological systems in terms of circuits -- sets of molecular or cellular components that interact with another in specific ways.

The most-encountered FFLs¶

While FFLs in general are motifs, some FFLS are more often encountered than others. In the figure below, using data taken from a review by Uri Alon, we see relative abundance of the eight different FFLs in E. coli and S. cerevisiae. Two FFLs, C1-FFL and I1-FFL, stand out as having much higher abundance than the other six. We will focus our study on these two in this chapter.

In [3]:
# Data based on Alon, Nature Rev. Genet., 2007, https://doi.org/10.1038/nrg2102
species = ["yeast", "E. coli"]
ffls = reversed(["C1 ", "C2 ", "C3 ", "C4 ", "I1 ", "I2 ", "I3 ", "I4 "])
data = {
    "species": species,
    "E. coli": reversed([0.464, 0.09, 0, 0, 0.374, 0.055, 0.017, 0]),
    "yeast": reversed([0.377, 0.035, 0.105, 0.08, 0.28, 0.027, 0.052, 0.044]),
}

x = [(ffl, sp) for ffl in ffls for sp in species]
frac = sum(zip(data["E. coli"], data["yeast"]), ())

source = bokeh.models.ColumnDataSource(data=dict(x=x, frac=frac))

p = bokeh.plotting.figure(
    y_range=bokeh.models.FactorRange(*x),
    frame_height=450,
    title="Relative abundance of FFLs",
)

p.hbar(
    y="x",
    left=0,
    right="frac",
    height=0.9,
    source=source,
    fill_color=bokeh.transform.factor_cmap(
        "x", palette=colors, factors=species, start=1, end=2
    ),
    line_color="white",
)

p.x_range.start = 0
p.y_range.range_padding = 0.05
p.yaxis.group_label_orientation = "horizontal"
p.ygrid.grid_line_color = None

bokeh.io.show(p)

Logic of regulation by two transcription factors¶

Because X and Y both regulate Z in an FFL, we need to specify how they collaborate in the regulation.

For the sake of illustration, let us assume we are discussing C1-FFL, where X activates Z and Y also activates Z. One can imagine a scenario where both X and Y need to be present to turn on Z. For example, they could be binding partners that together serve to recruit polymerase to the promoter. We call this AND logic. In other words, to get expression of Z, we must have X AND Y. Conversely, if either X or Y may each alone activate Z, we have OR logic. That is, to get expression of Z, we must have X OR Y.

So, to fully specify an FFL, we need to also specify the logic, either AND or OR, of how Z is regulated. Including choice of logic gives a total of 16 possible FFLs.

We are now left with the task of figuring out how to mathematically encode AND and OR logic. Before doing so, we note that, as discussed previously, we are using Hill functions, which are phenomenological functions describing how effectors may regulate gene expression capturing both the necessary concentration of effector ($k$) and the ultrasensitivity of the regulation ($n$). When the molecular details of the regulation mechanics of an effector are known, we may derive the appropriate functions describing gene expression regulation rather than using Hill function. Similarly, for two effectors, we could also derive the functions from the molecular details and discover what kind of logic emerges. See, for example, this 2005 paper by Bintu and coworkers. We often do not know the molecular details, and Hill functions and the two-effector variants thereof we present below are quite useful in analyzing the properties of circuit architectures.

We now proceed to formally write mathematical expressions for the dynamics of a gene product Z under regulatory control of effectors X and Y. The dynamics of the concentration of Z may be written as

\begin{align} \frac{\mathrm{d}z}{\mathrm{d}t} = \beta \,f(x, y) - \gamma z, \end{align}

where the lowercase letters denote the concentrations of the respective species.

Our goal is to specify the dimensionless regulatory function $f(x, y)$ that encodes how X and Y may together regulate Z. Our approach is to assign a "weight" to each state of a promoter region. With two effectors, X and Y, the promoter region could be unbound, bound with X, bound with Y, or bound with both X and Y. To get the regulatory function, we sum the weights of states that allow polymerase binding and divide by the sum of all weights. This gives the fraction of time that expression of the gene is "on." For example, if X and Y are both activators and they together have AND logic, we have

\begin{align} f(x, y) = \frac{\text{X and Y bound weight}}{(\text{unbound weight}) + (\text{X bound weight}) + (\text{Y bound weight}) + (\text{X and Y bound weight})} \end{align}

The weights are chosen to give Hill-like functions.

promoter region state weight dimensionless weight
unbound $$1$$ $$1$$
X bound $$(x/k_x)^{n_x}$$ $$x^{n_x}$$
Y bound $$(y/k_y)^{n_y}$$ $$y^{n_y}$$
X and Y bound $$(x/k_x)^{n_x}\,(y/k_y)^{n_y}$$ $$x^{n_x}\,y^{n_y}$$

The dimensionless weights are given by substituting $x \leftarrow x/k_x$ and $y \leftarrow y/k_y$. We will use the dimensionless versions of these functions henceforth. We note that the denominator of the regulatory function $f(x,y)$ is always the same,

\begin{align} 1 + x^{n_x} + y^{n_y} + x^{n_x} y^{n_y} = (1 + x^{n_x})(1 + y^{n_y}). \end{align}

Alternatively, we could have a structure where maximally only one of the two effectors may be bound at a time (for example due to steric reasons), in this case the states and weights are given in the table below.

promoter region state weight dimensionless weight
unbound $$1$$ $$1$$
X bound $$(x/k_x)^{n_x}$$ $$x^{n_x}$$
Y bound $$(y/k_y)^{n_y}$$ $$y^{n_x}$$

In this case, the denominator for all of the regulatory functions is $1 + x^{n_x} + y^{n_y}$. We will refer to such regulatory functions as corresponding to "single occupancy."

With this prescription, let us proceed to write the regulatory functions $f(x, y)$ for various architectures.

Logic with two activators¶

Let us start first with X and Y, both activating, with AND logic, as seen in the C1-FFL and I4-FFL. To help conceptualize how the logic translates into expression of Z before we get into the mathematical expressions, we can construct a truth table for whether or not Z is on, given the on/off status of X and Y. The truth table is shown below, with a zero entry meaning that the gene is not on and a one entry meaning it is on.

X Y Z
0 0 0
0 1 0
1 0 0
1 1 1

We can also construct a truth table for OR logic with X and Y both activating.

X Y Z
0 0 0
0 1 1
1 0 1
1 1 1

Following the above prescription, the dimensionless regulatory functions are

\begin{align} &\text{AND logic: } f(x,y) = \frac{x^{n_x} y^{n_y}}{(1 + x^{n_x})(1 + y^{n_y})},\\[1em] &\text{OR logic: } f(x,y) = \frac{x^{n_x} + y^{n_y} + x^{n_x} y^{n_y}}{(1 + x^{n_x})(1 + y^{n_y})}. \end{align}

If only single-occupancy is allowed, the gene can never be activated with AND logic, and the regulatory function with OR logic is

\begin{align} &\text{OR logic (single occupancy): } f(x,y) = \frac{x^{n_x} + y^{n_y}}{1 + x^{n_x} + y^{n_y}}. \end{align}

We can make plots of these regulatory functions to demonstrate how they represent the respective logic. To accentuate the logic, we will choose very sharp Hill functions $n_x = n_y = 20$.

In [4]:
# Get x and y values for plotting
x_log = np.logspace(-2, 2, 200)
y_log = np.logspace(-2, 2, 200)
x = np.linspace(0, 2, 200)
y = np.linspace(0, 2, 200)
xx, yy = np.meshgrid(x, y)
xx_log, yy_log = np.meshgrid(x_log, y_log)

# Parameters (steep Hill functions)
nx = 20
ny = 20

# Generate plots
p_and = xyz_im_plot(
    xx,
    yy,
    biocircuits.aa_and(xx, yy, nx, ny),
    xx_log,
    yy_log,
    biocircuits.aa_and(xx_log, yy_log, nx, ny),
    title="two activators, AND logic",
)
p_or = xyz_im_plot(
    xx,
    yy,
    biocircuits.aa_or(xx, yy, nx, ny),
    xx_log,
    yy_log,
    biocircuits.aa_or(xx_log, yy_log, nx, ny),
    title="two activators, OR logic",
)
p_or_single = xyz_im_plot(
    xx,
    yy,
    biocircuits.aa_or_single(xx, yy, nx, ny),
    xx_log,
    yy_log,
    biocircuits.aa_or_single(xx_log, yy_log, nx, ny),
    title="two act., OR logic, single occ.",
)


bokeh.io.show(
    bokeh.layouts.column(
        bokeh.layouts.row(p_and, bokeh.models.Spacer(width=30), p_or),
        bokeh.models.Spacer(height=20),
        bokeh.layouts.row(bokeh.models.Spacer(width=300), p_or_single),
    )
)

Here, purple indicates that $f(x, y)$ is zero and yellow indicates that $f(x, y)$ is one. With AND logic, both X and Y must have high concentrations for Z to be expressed. Conversely, for OR logic, X or Y or both can be in high concentrations for Z to be expressed, but if neither is high enough, Z does not get expressed. These graphical representations of the mathematical expressions for regulation indeed match the conceptual truth tables we started with.

Connection to logic gates¶

When two "input" effectors regulate the expression of a single "output" gene, we are tempted to connect the circuit architectures to logic gates. This is both useful and dangerous.

First, we will discuss the utility. Boolean algebra is a very powerful tool in developing circuits in digital electronics, and may also be a powerful framework for designing biological circuits. Briefly, Boolean algebra deals with only trues and falses, or ones and zeros. It has three fundamental operations, conjuction (∧), disjunction (∨), and negation (¬). They are defined such that

\begin{align} &a \land b = \left\{\begin{array}{ll} 1 & \text{if } a=b=1 \\ 0 & \text{otherwise}, \end{array} \right.\\[1em] &a \lor b = \left\{\begin{array}{ll} 0 & \text{if } a=b=0 \\ 1 & \text{otherwise}, \end{array} \right.\\[1em] &\lnot a = \left\{\begin{array}{ll} 0 & \text{if } a=1 \\ 1 & \text{if } a=0. \end{array} \right. \end{align}

One could think of two activators X and Y regulating expression of a gene Z with AND logic as Z = X ∧ Y. The relation X ∧ Y has a name; it is called an AND gate. The other architectures also represent logic gates. Below is a table of the analogous logic gates and Boolean algebra expressions for the two-effector regulation architectures we have considered.

X Y regulatory logic idealized logic gate Boolean algebra
activator activator AND AND X ∧ Y
activator activator OR OR X ∨ Y
repressor repressor AND NOR ¬X ∧ ¬Y = ¬(X ∨ Y)
repressor repressor OR NAND ¬X ∨ ¬Y = ¬(X ∧ Y)
activator repressor AND NIMPLY X ∧ ¬Y
activator repressor OR IMPLY* X ∨ ¬Y

*An IMPLY gate has a Boolean algebraic representation of ¬X ∨ Y, which we would get if we had arbitrarily chosen X to be the repressor instead of Y.

Now, let's consider the danger in using digital logic with these circuits. While thinking digitally for these circuits has its merit (indeed, we used a giant Hill coefficient in making the images above showing the expression levels of Z as a function of X and Y concentration), we must always remember that biological circuits are more fuzzy. As an example, let's look at how the one repressor/one activator system looks with a Hill coefficient of two.

In [5]:
p_and = xyz_im_plot(
    xx,
    yy,
    biocircuits.ar_and(xx, yy, 2, 2),
    xx_log,
    yy_log,
    biocircuits.ar_and(xx_log, yy_log, 2, 2),
    title="X act., Y rep., AND logic",
)
p_or = xyz_im_plot(
    xx,
    yy,
    biocircuits.ar_or(xx, yy, 2, 2),
    xx_log,
    yy_log,
    biocircuits.ar_or(xx_log, yy_log, 2, 2),
    title="X act., Y rep., OR logic",
)

bokeh.io.show(bokeh.layouts.row(p_and, bokeh.models.Spacer(width=30), p_or))

Exercise: Design a XNOR (XAND) logic gate¶

Assume that under normal conditions either of two metabolites A and B is present but never both. However, if both metabolites are missing or present simultaneously a disease may develop. Design a logic gate combination which is activated when both metabolites are present or absent and otherwise deactive.

Feedforward loop classes

  1. Formulate a truth table.
  2. Think about the genetic components and levels needed to accomplish the logic gate.
  3. Combine the elements with a mathematical model that represents molecular mechanisms (assume a single occupancy model).
In [8]:
# %load Snippets/BioMotifSim_XNOR_ori.py
# Get x and y values for plotting

x_log = np.logspace(-2, 2, 200)
y_log = np.logspace(-2, 2, 200)
x = np.linspace(0, 2, 200)
y = np.linspace(0, 2, 200)
xx, yy = np.meshgrid(x, y)
xx_log, yy_log = np.meshgrid(x_log, y_log)

# Parameters (steep Hill functions)
nx = 10
ny = 10

def myresponse(x, y, nx, ny):
    # Add equation for the interaction of transcription factors A and B based on the input x and y.
    # Use the Hill function with OR logic, single occupancy from above.
    A = None # Add your code here
    B = None # Add your code here
    return None # Add your code here

# Generate plots
p_and = xyz_im_plot(
    xx,
    yy,
    myresponse(xx, yy, nx, ny),
    xx_log,
    yy_log,
    myresponse(xx_log, yy_log, nx, ny),
    title="XNOR logic gate",
)


bokeh.io.show(
    bokeh.layouts.column(
        bokeh.layouts.row(p_and, bokeh.models.Spacer(width=30)),
    )
)
# %load Snippets/BioMotifSim_XNOR_sol.py

Regulatory functions and their derivatives¶

As we proceed through analysis of biological circuits, we will use the regulatory functions we have just derived, in addition to activating and repressive Hill functions, extensively. For convenience, these functions and their derivatives with respect to $x$ and $y$ are in Appendix D.

The biocircuits package and regulatory functions¶

The biocircuits package (GitHub) contains the regulatory functions we have just described. The available regulatory functions and call signatures are:

  • Repressive Hill function: biocircuits.rep_hill(x, n)
  • Activating Hill function: biocircuits.act_hill(x, n)
  • Two activators with AND logic: biocircuits.aa_and(x, y, nx, ny)
  • Two activators with OR logic: biocircuits.aa_or(x, y, nx, ny)
  • Two activators with AND logic, single occupancy: biocircuits.aa_or_single(x, y, nx, ny)
  • Two repressors with AND logic: biocircuits.rr_and(x, y, nx, ny)
  • Two repressors with OR logic: biocircuits.rr_or(x, y, nx, ny)
  • Two repressors with AND logic, single occupancy: biocircuits.rr_and_single(x, y, nx, ny)
  • One activator and one repressor with AND logic: biocircuits.ar_and(x, y, nx, ny)
  • One activator and one repressor with OR logic: biocircuits.ar_or(x, y, nx, ny)
  • One activator and one repressor with AND logic, single occupancy: biocircuits.ar_and_single(x, y, nx, ny)
  • One activator and one repressor with OR logic, single occupancy: biocircuits.ar_or_single(x, y, nx, ny)

It is important to note that the inputs x and y are dimensionless. In the case of one activator and one repressor, x is always assumed to the the concentration of the activator and y that of the repressor.

The code comprising the functions are simply expressions of the mathematical equations given above using Numpy arrays. For example, the contents of biocircuits.rr_and() is given below.

def rr_and(x, y, nx, ny):
    """Dimensionless production rate for a gene regulated by two
    repressors with AND logic in the absence of leakage.

    Parameters
    ----------
    x : float or NumPy array
        Concentration of first repressor.
    y : float or NumPy array
        Concentration of second repressor.
    nx : float
        Hill coefficient for first repressor.
    ny : float
        Hill coefficient for second repressor.

    Returns
    -------
    output : NumPy array or float
        1 / (1 + x**nx) / (1 + y**ny)
    """
    return 1 / (1 + x ** nx) / (1 + y ** ny)

These functions were used in generating the plots above, and we will use them going forward in this chapter as we numerically evaluate the dynamical equations of FFLs and beyond.

The C1-FFL circuit enables sign-sensitive delay¶

Now that we have laid the computational groundwork, we will proceed to an analysis of the first of the two over-represented FFLs, the C1-FFL. For reference, here again are the dimensionless dynamical equations:

\begin{align} \frac{\mathrm{d}y}{\mathrm{d}t} &= \beta\,\frac{(\kappa x)^{n_{xy}}}{1 + (\kappa x)^{n_{xy}}} - y, \\[1em] \gamma^{-1}\frac{\mathrm{d}z}{\mathrm{d}t} &= \frac{x^{n_{xz}} y^{n_{yz}}}{(1 + x^{n_{xz}})\,(1+ y^{n_{yz}})} - z. \end{align}

Now, let us look at the dynamics for a sudden step up and step down in X. We will use dimensionless parameter values $\beta = 5$, $\gamma = \kappa = 1$, $n_{xy} = n_{yz} = 3$, and $n_{xy} = 5$.

In [57]:
# Parameter values
beta = 5
gamma = .5
kappa = 1e0
n_xy, n_yz = 3, 3
n_xz = 5

# Plot
p, _, _ = biocircuits.apps.plot_ffl(
    beta, gamma, kappa, n_xy, n_xz, n_yz, ffl="c1", logic="and", normalized=False, # t_step_down=1,
)
bokeh.io.show(p)

The I1-FFL with AND logic is a pulse generator¶

We now turn our attention to the other over-represented circuit, the I1-FFL. As a reminder, here is the structure of the circuit.

FFL abundance

X activates Y and Z, but Y represses Z. We can use the expressions for production rate under AND and OR logic for one activator/one repressor that we showed above in writing down our dynamical equations. Here, we will consider AND logic. The dimensionless dynamical equations are

\begin{align} \frac{\mathrm{d}y}{\mathrm{d}t} &= \beta\,\frac{(\kappa x)^{n_{xy}}}{1+(\kappa x)^{n_{xy}}} - y,\\[1em] \gamma^{-1}\,\frac{\mathrm{d}z}{\mathrm{d}t} &= \frac{x^{n_{xz}}}{(1 + x^{n_{xz}})\,(1 + y^{n_{yz}})} - z. \end{align}

In our first analysis of this circuit, we will investigate the response in Z to a sudden, sustained step in stimulus X. We will choose $\gamma = 10$, which means that the dynamics of Z are faster than Y.

In [7]:
# Parameter values
beta = 5
gamma = 10
kappa = 1
n_xy, n_yz = 3, 3
n_xz = 5
t = np.linspace(0, 5, 100)

# Set up and solve
p, _, _ = biocircuits.apps.plot_ffl(
    beta,
    gamma,
    kappa,
    n_xy,
    n_xz,
    n_yz,
    ffl="i1",
    logic="and",
    t=t,
    t_step_down=np.inf,
    normalized=False,
)
bokeh.io.show(p)

We see that Z pulses up and then falls down to its steady state value. This is because the presence X leads to production of Z due to its activation. X also leads to the increase in Y, and once enough Y is present, it can start to repress Z. This brings the Z level back down toward a new steady state where the production rate of Z is a balance between activation by X and repression by Y. Thus, the I1-FFL with AND logic is a pulse generator.

The accelerated response of the I1-FFL is observed experimentally¶

Mangan and coworkers (Mangan, et al., 2006) investigated an I1-FFL circuit that E. coli uses in its galactose utilization system. The circuit is shown below.

gal E system

As the "X" gene in this I1-FFL is CRP, the circuit is induced by sudden addition of cAMP, as in the arabinose and lactose circuits above. Mangan and coworkers investigated the response of the wild type circuit, as well as a mutant circuit where galS was deleted. This latter circuit lacks the feed forward loop, and the production of galETK is directly regulated by CRP.

In their experiment, the galE promoter was engineering to express GFP so they could monitor the dynamics of the circuit with fluorescence. The result is shown below.

In [59]:
# Plot data digitized from Mangan, et al., J. Molec. Biol., 2006
# https://doi.org/10.1016/j.jmb.2005.12.003

t_wt = np.array([
    0.07, 0.39, 0.71, 0.94, 1.2 , 1.45, 1.67, 1.9 , 2.14, 2.35, 2.55,
    2.74, 2.89, 3.05])

t_mut = np.array([
    0.05, 0.29, 0.58, 0.83, 1.05, 1.28, 1.53, 1.75, 1.96, 2.17, 2.37])

x_wt = np.array([
    0.04, 0.56, 1.11, 1.53, 1.73, 1.78, 1.67, 1.44, 1.3 , 1.2 , 1.11,
    1.05, 1.  , 1.  ])

x_mut = np.array([
    0.04, 0.16, 0.32, 0.46, 0.5 , 0.56, 0.62, 0.68, 0.71, 0.75, 0.79])

p = bokeh.plotting.figure(
    frame_height=250,
    frame_width=350,
    x_axis_label='time (cell divisions)',
    y_axis_label="normalized level",
)

p.circle(t_wt, x_wt, color=colors[0], legend_label="wild type")
p.circle(t_mut, x_mut, color=colors[1], legend_label="galS mutant")

p.legend.location = "bottom_right"

bokeh.io.show(p)

We see that indeed the wild type I1-FFL architecture speeds up the response to the cAMP input, complete with the overshoot we expect from an I1-FFL circuit.


References¶

  • Alon, U., Network motifs: Theory and experimental approaches, Nat. Rev. Genet., 8, 450–461, 2007. (link)
  • Bintu, L., et al., Transcriptional regulation by the numbers: models, Curr. Op. Genet. Dev., 15, 116–124, 2005.(link)
  • Kalir, S., Mangan, S., and Alon, U., A coherent feed-forward loop with a SUM input function prolongs flagella expression in Escherichia coli, Molec. Sys. Biol., 1, 2005.006, 2005. (link)
  • Mangan, S., et al., The incoherent feed-forward loop accelerates the response-time of the gal system of Escherichia coli, J. Molec. Biol., 356, 1073–1081, 2006. (link)
  • Milo, R., et al., Network motifs: Simple building blocks of complex networks, Science, 298, 824–827, 2002. (link)
  • Milo, R., et al., Superfamilies of evolved and designed networks, Science, 303, 1538–1542, 2004.(link)
  • Newman, M. E. J., Strogatz, S. H., and Watts, D. J., Random graphs with arbitrary degree distributions and their applications, Phys. Rev. E, 64, 026118, 2001. (link)
  • Shen-Orr, S. S., et al., Network motifs in the transcriptional regulation network of Escherichia coli, Nature Genetics, 31, 64–68, 2002. (link)

Computing environment¶

In [60]:
%load_ext watermark
%watermark -v -p numpy,scipy,bokeh,biocircuits,jupyterlab
Python implementation: CPython
Python version       : 3.11.3
IPython version      : 8.12.0

numpy      : 1.24.3
scipy      : 1.10.1
bokeh      : 3.1.1
biocircuits: 0.1.11
jupyterlab : 4.0.0